A storage system is a computer that provides storage services relating to the organization of information on writeable persistent storage devices, such as non-volatile memories and/or disks. The storage system typically includes a storage operating system that implements a file system to logically organize the information as a hierarchical structure of data containers, such as files and directories on, e.g., the disks. Each “on-disk” file may be implemented as set of data structures, e.g., disk blocks, configured to store information, such as the actual data for the file. A directory, on the other hand, may be realized as a specially formatted file in which information about other files and directories are stored.
The storage system may be further configured to operate according to a client/server model of information delivery to thereby allow many clients to access files and directories stored on the system. In this model, the client may comprise an application executing on a computer that “connects” to the storage system over a computer network, such as a point-to-point link, shared local area network, wide area network or virtual private network implemented over a public network, such as the Internet. Each client may request the services of the storage system by issuing file system protocol messages or requests, such as the conventional Network File System (NFS) protocol requests, to the system over the network identifying one or more files to be accessed. In response, a file system executing on the storage system services the request and returns a reply to the client.
Many versions of the NFS protocol require reply caches for their operation. A reply cache may serve many purposes, one of which is to prevent re-execution (replay) of non-idempotent operations by identifying duplicate requests. By caching reply information for such operations, replies to duplicate requests may be rendered from cached information, as opposed to re-executing the operation with the file system. For example, assume a client issues an NFS request to the storage system, wherein the request contains a non-idempotent operation, such as a rename operation that renames, e.g., file A to file B. Assume further that the file system receives and processes the request, but the reply to the request is lost or the connection to the client is broken. A reply is thus not returned to the client and, as a result, the client resends the request. The file system then attempts to process the rename request again but, since file A has already been renamed to file B, the system returns a failure, e.g., an error reply, to the client (even though the operation renaming file A to file B had been successfully completed). A reply cache attempts to prevent such failures by recording the fact that the particular request was successfully executed, so that if it were to be reissued for any reason, the same reply will be resent to the client (instead of re-executing the previously executed request, which could result in an inappropriate error reply).
Typically, the reply cache has been implemented in volatile memory of a storage system. This poses the issue that if retransmission of the request (e.g., an NFS request) occurs as a result of non-responsiveness while the storage system reboots, a failure similar to that described above can occur. For example, suppose that the storage system processes the request to rename file A to file B and, after processing the request, the storage system powers-down and performs a reboot operation. Since the rename operation had been effected in the file system image before the reboot operation, re-execution of the request results in a spurious error; if the reply cache is volatile, there is no way to prevent this error. In other words, when the storage system powers down and reboots, the contents of the reply cache are lost.
A solution to the above-described problem is to implement the reply cache in persistent storage. However, previous attempts to implement such a reply cache encountered a number of difficulties. For instance, persistent storage of reply cache information on, e.g., disk typically imposes too great a performance penalty for general use. That is, the input/output (I/O) latency associated with accessing disk for reply cache information imposes a substantial performance penalty. On the other hand, storage in non-volatile memory, such as random access memory, is often expensive because of the storage space requirements. Here, the amount of non-volatile memory needed to accommodate a typical size for the reply cache is substantial and, thus, often prohibitively expensive.